package hydrap2p.download;

import hydrap2p.library.Range;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.thrift.TException;

/**
 * The Class DownloaderEventForwarder.
 */
public class DownloaderEventForwarder {
	
	/**
	 * Forward event new source.
	 * 
	 * @param subscribers the subscribers
	 * @param d the d
	 * @param source the source
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventNewSource(List<DownloadSubscriber> subscribers, Download d, Source source) {
		List<DownloadSubscriber> failed = new ArrayList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().newSource || service.getType().all) {
				try {
					service.connection.newSource(d.getUid(), source);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event new download.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventNewDownload(List<DownloadSubscriber> subscribers, long uid) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().newDownload || service.getType().all) {
				try {
					service.connection.newDownload(uid);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}
	
	/**
	 * Forward event removed download.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventRemovedDownload(List<DownloadSubscriber> subscribers, long uid) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().removedDownload || service.getType().all) {
				try {
					service.connection.removedDownload(uid);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update download state.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param state the state
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateDownloadState(List<DownloadSubscriber> subscribers, long uid, DownloadState state) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().downloadState || service.getType().all) {
				try {
					service.connection.updateDownloadState(uid, state);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event removed source.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param source the source
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventRemovedSource(List<DownloadSubscriber> subscribers, long uid, Source source) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().removedSource || service.getType().all) {
				try {
					service.connection.removedSource(uid, source);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update source.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param source the source
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateSource(List<DownloadSubscriber> subscribers, long uid, Source source) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().changedSource || service.getType().all) {
				try {
					service.connection.removedSource(uid, source);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update downloaded range.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param list the list
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateDownloadedRange(List<DownloadSubscriber> subscribers, long uid, List<Range> list) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().downloadedRanges || service.getType().all) {
				try {
					service.connection.updateDownloadedRanges(uid, list);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update available ranges.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param list the list
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateAvailableRanges(List<DownloadSubscriber> subscribers, long uid, List<Range> list) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().availableRanges || service.getType().all) {
				try {
					service.connection.updateAvailableRanges(uid, list);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update verified ranges.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param list the list
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateVerifiedRanges(List<DownloadSubscriber> subscribers, long uid, List<Range> list) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().verifiedRanges || service.getType().all) {
				try {
					service.connection.updateVerifiedRanges(uid, list);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update download progress.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param downloaded the downloaded
	 * @param total the total
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateDownloadProgress(List<DownloadSubscriber> subscribers, long uid, Source source, long downloaded, long total) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().downloadProgress || service.getType().all) {
				try {
					service.connection.updateDownloadProgress(uid, source, downloaded, total);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}

	/**
	 * Forward event update verified progress.
	 * 
	 * @param subscribers the subscribers
	 * @param uid the uid
	 * @param verified the verified
	 * @param total the total
	 * @return the list
	 */
	public List<DownloadSubscriber> forwardEventUpdateVerifiedProgress(List<DownloadSubscriber> subscribers, long uid, long verified, long total) {
		List<DownloadSubscriber> failed = new LinkedList<DownloadSubscriber>();

		for(DownloadSubscriber service : subscribers) {
			if(service.getType().verifiedProgress || service.getType().all) {
				try {
					service.connection.updateVerifiedProgress(uid, verified, total);
				} catch(TException e) {
					// This connection has failed, remove it from the listeners
					failed.add(service);
				}
			}
		}

		return failed;
	}
}
